﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using LevelEditor.Objects;
using System.Drawing;

namespace LevelEditor.Components.Layers
{
    public class LayerPanel : FlowLayoutPanel
    {
        private static LayerItem selected;
        public static LayerItem CurrentLayer
        {
            get { return selected; }
        }

        private LevelEditor editor;

        private int distanceForDrag;
        private Point mouseDownPosition;
        private bool doDragging;

        public LayerPanel() : base()
        {
            this.ControlAdded += LayerPanel_ControlAdded;
            this.mouseDownPosition = Point.Empty;
            this.distanceForDrag = 2;
            this.AutoScroll = true;
        }

        public void SetForm(LevelEditor editor)
        {
            this.editor = editor;
        }

        void LayerPanel_ControlAdded(object sender, ControlEventArgs e)
        {
            int layerIndex = this.Controls.GetChildIndex(e.Control);

            e.Control.MouseDown += (s, ev) => LayerPanel_MouseDown(e.Control, layerIndex);
            e.Control.MouseUp += (s, ev) => LayerPanel_MouseUp(e.Control, layerIndex);
            e.Control.MouseMove += LayerPanel_MouseMove;
            e.Control.DragDrop += LayerPanel_DragDrop;
            e.Control.DragEnter += Control_DragEnter;

            ScrollControlIntoView(e.Control);
            
            UpdateIndexes();
        }

        void Control_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }

        void LayerPanel_DragDrop(object sender, DragEventArgs e)
        {
            LayerItem item = (LayerItem)e.Data.GetData(typeof(LayerItem));

            int newIndex = ((LayerItem)sender).myLayer.LayerIndex;
            ((LayerItem)sender).myLayer.LayerIndex = item.myLayer.LayerIndex;
            item.myLayer.LayerIndex = newIndex;

            this.Controls.SetChildIndex(item, this.Controls.GetChildIndex(((LayerItem)sender)));

            SelectLayer(item);
        }

        void LayerPanel_MouseUp(object sender, int layerIndex)
        {
            doDragging = false;
        }

        void LayerPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (!doDragging) return;

            if (Util.Util.Distance(mouseDownPosition, Cursor.Position) > distanceForDrag)
            {
                doDragging = false;
                ((LayerItem)sender).DoDragDrop((LayerItem)sender, DragDropEffects.Copy | DragDropEffects.Move);
            }
        }

        void LayerPanel_MouseDown(object sender, int layerIndex)
        {
            mouseDownPosition = Cursor.Position;
            SelectLayer((LayerItem)sender);

            doDragging = true;
        }

        public void SelectLayer(LayerItem item)
        {
            if (!this.Controls.Contains(item)) return;

            if (selected != null) selected.Deselect();

            selected = item;

            selected.Select();

            this.editor.stage1.DrawLayerGrid(item);
        }

        // update the indexes of the layers... Controls who is in the front
        public void UpdateIndexes()
        {
            int tp = 0;
            for (int k = 0; k < this.Controls.Count; k++)
            {
                ((LayerItem)this.Controls[k]).myLayer.LayerIndex = tp++;
            }
        }

        public void DeleteCurrentLayer()
        {
            if (this.Controls.Count <= 0) return;

            selected.Delete();
            //this.Controls.Remove(selected);
            
            if (this.Controls.Count > 0)
                SelectLayer(((LayerItem)this.Controls[0]));
        }

        public void CopyCurrentLayer()
        {
            if (selected == null) return;

            LayerItem item = new LayerItem(this.editor, "copy " + selected.LayerName.Text);
            
            for (int k = 0; k < selected.myLayer.Count; k++)
            {
                Tile newTile = new Tile(this.editor);
                newTile.Image = selected.myLayer[k].Image;
                newTile.Name = selected.myLayer[k].Name;
                newTile.ImageFormat = selected.myLayer[k].ImageFormat;
                newTile.Height = selected.myLayer[k].Height;
                newTile.Width = selected.myLayer[k].Width;
                newTile.Location = selected.myLayer[k].Location;

                this.editor.stage1.Controls.Add(newTile);
                item.myLayer.Add(newTile);

                newTile.MyLayer = item;
            }

            this.Controls.Add(item);
        }

        public void NewLayer(string name, int cols, int rows, int tileWidth, int tileHeight)
        {
            LayerItem item = new LayerItem(this.editor, name);
            item.Cols = cols;
            item.Rows = rows;
            item.TileHeight = tileHeight;
            item.TileWidth = tileWidth;
            this.Controls.Add(item);

            SelectLayer(item);
        }

        public void UpdateLayerPreview()
        {
            for (int k = 0; k < this.Controls.Count; k++)
           {
                ((LayerItem)this.Controls[k]).GeneratePreview();
            }
        }

        public bool HasLayer()
        {
            return Controls.Count > 0;
        }


        public void HideAllGrids()
        {
            for (int k = 0; k < this.Controls.Count; k++)
            {
                ((LayerItem)this.Controls[k]).ShowingGrid = false;
            }
        }
    }
}
